//******************************************************************/
//版本说明:
//V0.1		2019-01-31	11:00	yshao	灯饰控制器通讯顶层
//******************************************************************/
`timescale	1ps/1ps
//`define	BOOT_MODE	1

module a1_comm_top(
		//时钟，按键，Led
                input	wire		sclkin,
                input   wire		key_in,
 		output	wire		led_g,
               
		//输出复位和时钟
                output	wire		resetb,
                output	wire		sclk,
 		output	wire		oclk,
                output	wire		sa_clk,
 		output	wire		clk_25M,

                //MCU通讯接口
		input	wire		mcu_fpga_ctrl,		//mcu到fpga的模式控制信号

		input	wire		mcu_spi_fpga,		//spi工作在通讯模式		
		input	wire		mcu_spi_clk,
		input	wire		mcu_spi_mosi,
		output	reg		mcu_spi_miso,

		output	wire		spi2_cs,
		output	wire		spi2_clk,
		output	wire		spi2_mosi,
								
		//PHY通讯接口
		output	wire		phy_rst,
		output	wire		phy_mdc,
		inout	tri		phy_mdio,

		input	wire		gp0_rxc,
		input	wire		gp0_rxdv,
		input	wire	[3:0]	gp0_rxd,
		output	wire		gp0_txc,
		output	wire		gp0_txen,
		output	wire	[3:0]	gp0_txd,
		
		input	wire		gp1_rxc,
		input	wire		gp1_rxdv,
		input	wire	[3:0]	gp1_rxd,
		output	wire		gp1_txc,
		output	wire		gp1_txen,
		output	wire	[3:0]	gp1_txd,

		//SD卡通讯接口
		output	wire		sd_clk,
		inout	tri		sd_cmd_sdi,
		input	wire		sd_dat0_sdo,
		input	wire		sd_dat1,
		input	wire		sd_dat2,
		inout	wire		sd_dat3_cs,
		input	wire		sd_cd,
		input	wire		sd_wp,

		//分频时钟
		output	wire	[20:0]	time_us,
		output	wire	[20:0]	sync_us,

		//MCU总线接口
		output	wire		mcu_set_d_ok,
		output	wire		mcu_ext_d_ok,
		output	wire	[31:0]	mcu_set_addr,
		output	wire	[7:0]	mcu_set_data,
		input	wire	[7:0]	mcu_rd_data,
                
		//PHY总线接口
		output	wire		init_mode,
		output	wire		set_d_ok,
		output	wire		ext_d_ok,
		output	wire	[31:0]	set_addr,
		output	wire	[7:0]	set_data,
		input	wire	[7:0]	rd_data,
                
		//显示数据接口
		output	reg		vs,
		output	reg		ds,
		output	reg	[7:0]	data,
		output	reg		h_start,
		output	reg	[10:0]	h_num,
		output	wire		l2048_mode,
		output	reg		artnet_mode,
                
		output	wire	[15:0]	state,
		output	wire	[1:0]	color_restore_type,
		output	wire	[7:0]	testmode,
		output	wire	[8:0]	cascade_light,
		
		output  wire		black,

		//背板控制接口
		input	wire		fpga_dmx_send,
		output	reg		mcu_dmx_ten,

		//SD卡播放指示
		output	wire		input_L9,
		output	reg		input_artnet,
		output	wire		sd_valid,
		input	wire		sd_play_flag,
		input	wire		local_dis_flag,
		
		//SD卡播放操作接口
		input	wire		sd_play_clk,
		input	wire		sd_play_cmd_out,
		input	wire		sd_play_cmd_oe,
		output	reg	[3:0]	sd_play_data,
		//SD发送数据包接口
		input	wire		force_send_play,
		input	wire		send_flag_dis,
		input	wire		pre_flag_dis,
		input	wire	[7:0]	send_data_dis,
		
		//调试接口
		output	wire	[31:0]	tout
		);

//****************************************************************
//		内部信号
//****************************************************************
wire		oclk_err, key_press;

wire		local_depth_en, cas_depth_adj;
wire	[9:0]   current_depth;

wire		rec_flag_a, rec_flag, rec_error;
wire	[7:0]	rec_data;
reg		send_flag, pre_flag;
reg	[7:0]	send_data;
wire	[1:0]	rec_vendor;
wire		yt_vs_pre, redu_flag, blank_flag;
wire	[7:0]	phy_state;

wire		send_flag_mcu, pre_flag_mcu, send_flag_com, pre_flag_com;
wire	[7:0]	send_data_mcu, send_data_com;                

//MUC接口相关
wire		mcu_com_miso, mcu_sd_miso, mcu_flash_miso;

//Flash相关
wire		flash_CS_n_fpga, flash_SCK_fpga, flash_SI_fpga, flash_SO_fpga;

//显示数据相关
wire    [10:0]  h_total, l_total;
wire		vs_a, ds_a, v_start_a, h_start_a;
wire	[7:0]	data_a;
wire	[10:0]	h_num_a;


//**********mcu-fpga**************
wire		op_addr_mask;

wire		spi_rec_flag;
wire	[7:0]	spi_rec_data;
wire		spi_rec_error;
wire	[1:0]	spi_rec_vendor;

wire		spi_send_flag;
wire		spi_send_pre;
wire	[7:0]	spi_send_data;

wire		mcu_flash_en, mcu_sd_en;
wire	[7:0]	fpga_state;

wire	[7:0]	rd_data_a, rd_data_d;
wire		sub_mode;
//**********显示和输出**************
wire		vs_out;
wire		ds_b, h_start_b;
wire	[7:0]	data_b;
wire	[2:0]	h_num_b;
wire		artnet_flag, artnet_en;
wire	[7:0]	l9_com_tout;

reg	[7:0]	a_over_count;

reg		force_send_mcu;
reg	[1:0]	mcu_force_port, force_send;

//**********调试用信号**********
wire	[7:0]	comm_tout, spi_tout, boot_tout;
wire	[15:0]	phy_tout;
wire	[31:0]	d_tout;

//**************************************************************
//			   参数定义
//**************************************************************


//**************************************************************
//			整体控制
//**************************************************************
//********时钟,复位,按键，LED指示单元********
sys_reset_clk sys_reset_clk(
		//输入时钟
		.sclkin(sclkin),
        
        	//输出复位和时钟
		.resetb(resetb),
		.sclk(sclk),
		.oclk(oclk),
		.sa_clk(sa_clk),
		.clk_25M(clk_25M),
        
        	//oclk错误指示
		.oclk_err(oclk_err),
        
        	//分频时钟
        	.time_us(time_us),
        	.sync_us(sync_us),
        	
		//按键检测
		.key_input(key_in),
		.key_press(key_press),
		
		//指示灯相关
		.G_flash(rec_flag | send_flag_dis),
		.nG_led(led_g),
	
		.tout()   
		);
               
//********复位控制********
reboot_ctrl reboot_ctrl(
		.resetb(resetb),
		.sclk(sclk),
		.clk_25M(clk_25M),
		
//	        .cmd_d_ok(ext_d_ok),
//	        .cmd_addr(set_addr),
//	        .cmd_data(set_data),
	        
	        .mcu_cmd_d_ok(mcu_ext_d_ok),
	        .mcu_cmd_addr(mcu_set_addr),
	        .mcu_cmd_data(mcu_set_data),
	        
		.tout(boot_tout)
		);
		
//********Flash读写控制********
flash_ctrl flash_ctrl(
		//控制选通
		.mcu_flash_en(mcu_flash_en),
		
		//MCU控制信号
	        .mcu_spi_cs(mcu_spi_cs),
	        .mcu_spi_clk(mcu_spi_clk),
	        .mcu_spi_mosi(mcu_spi_mosi),
	        .mcu_spi_miso(mcu_flash_miso),
	        
		//FPGA控制信号
	        .flash_CS_n_fpga(flash_CS_n_fpga),
	        .flash_SCK_fpga(flash_SCK_fpga),
	        .flash_SI_fpga(flash_SI_fpga),
	        .flash_SO_fpga(flash_SO_fpga),
	        
		.tout()
		);
		
//**************************************************************
//		   千兆级联模块
//**************************************************************    
phy_interface phy_interface(
		.resetb(resetb),
		.sclk(sclk),
		.clk_25M(clk_25M),
                
		.sub_mode(sub_mode),
		.local_depth(current_depth),
		.cas_depth_adj(cas_depth_adj),

		.tx_err_en(1'b0),
		.time_1ms(time_us[10]),
		.time_125ms(time_us[17]),	

		.gp0_rxc(gp0_rxc),
		.gp0_rxdv(gp0_rxdv),
		.gp0_rxd(gp0_rxd),
		.gp0_txc(gp0_txc),
		.gp0_txen(gp0_txen),
		.gp0_txd(gp0_txd),
		
		.gp1_rxc(gp1_rxc),
		.gp1_rxdv(gp1_rxdv),
		.gp1_rxd(gp1_rxd),
		.gp1_txc(gp1_txc),
		.gp1_txen(gp1_txen),
		.gp1_txd(gp1_txd),
		
		.rec_flag_a(rec_flag_a),
		.rec_flag(rec_flag),
		.rec_data(rec_data),
		.rec_error(rec_error),
		.rec_error_sync(),
		
		.force_send(1'b0),//force_send),
		.send_flag(1'b0),//send_flag),
		.pre_flag(1'b0),//pre_flag),
		.send_data(8'h0),//send_data),

		.rec_vendor(rec_vendor),
		.yt_vs_pre(yt_vs_pre),
		.input_active(input_L9),
		.redu_flag(redu_flag),
		.blank_flag(blank_flag),
		.phy_state(phy_state),
		
		.tout(phy_tout)
		);

//**************************************************************
//		   网口输出数据选通
//**************************************************************    
always	@(posedge sclk or negedge resetb)
	if (resetb==0) begin
		force_send_mcu	<= 1'b0;
		mcu_force_port	<= 2'b00;
		end
	else if ((mcu_ext_d_ok == 1) && (mcu_set_addr == 32'h00010300)) begin
		force_send_mcu	<= mcu_set_data[0];
		mcu_force_port	<= mcu_set_data[2:1];
		end

always	@(posedge sclk)
	if (force_send_mcu == 1) begin
		force_send <= mcu_force_port;
		send_flag <= send_flag_mcu;
		pre_flag <= pre_flag_mcu;
		send_data <= send_data_mcu;
		end
	else if (send_flag_mcu == 1) begin
		force_send <= 2'b00;
		send_flag <= 1'b1;
		pre_flag <= pre_flag_mcu;
		send_data <= send_data_mcu;
		end
	else if (send_flag_com == 1)begin
		force_send <= 2'b00;
		send_flag <= 1'b1;
		pre_flag <= pre_flag_com;
		send_data <= send_data_com;
		end
	else if ((force_send_play == 1) || ((input_L9 == 0) && (input_artnet == 0)))begin
		force_send <= 2'b11;
		send_flag <= send_flag_dis;
		pre_flag <= pre_flag_dis;
		send_data <= send_data_dis;
		end 
	else begin
		force_send <= 2'b00;
		send_flag <= 1'b0;
		pre_flag <= 1'b0;
		send_data <= 8'h0;
		end		
	

//**************************************************************
//		PHY通讯包解析
//**************************************************************        
//iColor通讯设置包解析
v8_phy_com_01 phy_comm(
		.resetb(resetb),
		.sclk(sclk),
		.time_1ms_sync(sync_us[10]),
		.sub_mode(sub_mode),
		
		//整体工作控制
		.init_mode(init_mode),

		//级联地址设定
		.local_depth_en(local_depth_en),
		.cas_depth_adj(cas_depth_adj),
		.current_depth(current_depth),

		//phy接口
		.rec_vendor(rec_vendor),
		.blank_flag(blank_flag),
		.redu_flag(redu_flag),
		.phy_state(phy_state),
		
		.rec_flag(rec_flag),
		.rec_error(rec_error),
		.rec_data(rec_data),
		
		.send_flag(send_flag_com),
		.pre_flag(pre_flag_com),
		.send_data(send_data_com),
		
		//PHY通讯转MCU标志
		.op_addr_mask(op_addr_mask),

		//内部寄存器设置总线
		.set_d_ok(set_d_ok),
		.set_addr(set_addr[15:0]),
		.set_data(set_data),
		
		.ext_d_ok(ext_d_ok),
		.ext_addr(set_addr[31:16]),
		
		//逐点调整数据设置总线
		.init_correct_d_ok(),
		.init_correct_addr(),
		.init_correct_data(),
		.load_adj_flag(),
		.load_picture_flag(),
		
		//调试用返回的状态数据
		.debug_data({cas_depth_adj,local_depth_en}),
		
		//其他状态数据
		.rd_data(rd_data_d),
		
		//Flash接口
		.flash_CS_n(flash_CS_n_fpga),
		.flash_SCK(flash_SCK_fpga),
		.flash_SI(flash_SI_fpga),
		.flash_SO(flash_SO_fpga),

		//调试信号接口
		.tout(comm_tout)
		);

//网口反馈数据
assign	rd_data_d = rd_data | rd_data_a;
		
//Artnet包iColor包ARP包转发MCU
//Artnet显示数据包提取
L9_com_ctrl_02 com_ctrl_b(
		.resetb(resetb),
		.sclk(sclk),
		.comm_en(~init_mode),

		.sub_mode(sub_mode),
		.current_depth(current_depth),
		
		.rec_flag(rec_flag_a),
		.rec_data(rec_data),
		.rec_error(rec_error),
		
		.blank_flag(blank_flag),
		.redu_flag(redu_flag),
		.time_1ms_sync(sync_us[10]),
		
		.op_addr_mask(op_addr_mask),

		.spi2_cs(spi2_cs),
		.spi2_clk(spi2_clk),
		.spi2_mosi(spi2_mosi),
		
		.artnet_flag(artnet_flag),
		.dsout(ds_b),
		.dout(data_b),
		.h_start(h_start_b),
		.h_num(h_num_b),
		.l2048_mode(),
		
		.tout(l9_com_tout)
		);

//iColor显示数据包提取
L9_data_rec_02 data_rec(
		.resetb(resetb),
		.sclk(sclk),
		
		//网口配置总线
		.set_d_ok(set_d_ok),
		.set_addr(set_addr),
		.set_data(set_data),
	        
		//MCU配置总线
		.mcu_ext_d_ok(mcu_ext_d_ok),
		.mcu_cmd_addr(mcu_set_addr),
		.mcu_cmd_data(mcu_set_data),

		//当前分控序号
		.current_depth(current_depth),

		//工作模式控制
		.init_mode(init_mode),
		.black(1'b0),
		
		//开机渐亮控制
		.test_vs(0),
		.local_test_en(0),
		.local_picture_en(0),        
		
		//多模块共用设置数据输出
		.h_total(h_total),
		.l_total(l_total),
		
		//PHY模块接口
		.mac_flag(rec_flag),
		.mac_data(rec_data),
		.mac_error(rec_error),
		.mac_vendor(rec_vendor),
		
		//显示数据输出
		.vsout(vs_a),
		.dsout(ds_a),
		.dout(data_a),
		.h_start(h_start_a),
		.h_num(h_num_a),
		.l2048_mode(l2048_mode),
		.artnet_en(artnet_en),
		
                //显示设置数据输出
		.state(state[7:0]),	
		.state_2(state[15:8]),
		.color_restore_type(color_restore_type),
		.testmode(testmode),
		.cascade_light(cascade_light),

		//调试用信号输出
		.tout(d_tout)
		);
		
//***********黑屏控制*****************
black_ctrl      black_ctrl(
		//时钟和复位
		.resetb(resetb),
		.sclk(sclk),
                
		//显示设置包配置
		.state(state[7:0]), 
                
		//PHY总线接口
		.init_mode(init_mode),
		.set_d_ok(set_d_ok),
		.set_addr(set_addr),
		.set_data(set_data),

		//其他输入
		.input_L9(input_L9),
		.input_artnet(input_artnet),
		.local_dis_flag(local_dis_flag),
                
		//标志输出
		.black(black),
		
		//调试接口
		.tout()   
                );  

//**************************************************************
//         显示数据存储与读取
//************************************************************** 
always @(posedge sclk or negedge resetb)
	if (resetb == 0)
		input_artnet <= 0;
	else if (artnet_en == 0)
		input_artnet <= 0;
	else if (artnet_flag == 1)
		input_artnet <= 1;
	else if (a_over_count[7] == 1)
		input_artnet <= 0;

always @(posedge sclk or negedge resetb)
	if (resetb == 0)
		a_over_count <= 0;
	else if (artnet_flag == 1)
		a_over_count <= 0;
	else if ((sync_us[10] == 1) && (a_over_count[7] == 0))
		a_over_count <= a_over_count + 1;
			
always @(posedge sclk)
	vs <= vs_a;
	
always @(posedge sclk)
	if (artnet_mode == 1) begin
		ds <= ds_b;
		h_num <= h_num_b;
		data <= data_b;
		h_start <= h_start_b;
	end
	else begin
		ds <= ds_a;
		h_num <= h_num_a;
		data <= data_a;
		h_start <= h_start_a;
	end

//**************************************************************
//		  MCU控制接口
//************************************************************** 
//MCU到FPGA的SPI接口
L9_spi_com_01 mcu_comm(
		.resetb(resetb),
		.sclk(sclk),
		.comm_en(~init_mode),
		
		//MCU到FPGA接口	
		.mcu_spi_cs(mcu_spi_fpga),
		.mcu_spi_clk(mcu_spi_clk),
		.mcu_spi_mosi(mcu_spi_mosi),
		.mcu_spi_miso(mcu_com_miso),

		//返回PHY数据包	
		.send_flag(send_flag_mcu),
		.pre_flag(pre_flag_mcu),
		.send_data(send_data_mcu),
		
		//PHY反馈接口
		.set_addr(set_addr),
		.rd_data(rd_data_a),
		
		//设备模式
		.sub_mode(sub_mode),
		
		.mcu_set_d_ok(mcu_set_d_ok),
		.mcu_set_addr(mcu_set_addr[15:0]),
		.mcu_set_data(mcu_set_data),
		
		.mcu_ext_d_ok(mcu_ext_d_ok),
		.mcu_ext_addr(mcu_set_addr[31:16]),
		
		.mcu_rd_data(mcu_rd_data),
		.fpga_state(fpga_state),

		//SD卡接口信号
		.mcu_sd_en(mcu_sd_en),
		//和Flash接口	
		.mcu_flash_en(mcu_flash_en),
		//PHY控制接口
		.phy_rst(phy_rst),
		.phy_mdc(phy_mdc),
		.phy_mdio(phy_mdio),

		//调试信号
		.tout(spi_tout)
		);

//assign	mcu_flash_en = 0;
assign	fpga_state = {sd_valid, sd_play_flag, input_L9, input_artnet, 1'b0, mcu_flash_en, mcu_sd_en, init_mode};

always @( * )
	if (mcu_sd_en == 1)
		mcu_spi_miso <= mcu_sd_miso;
	else if (mcu_flash_en == 1)
		mcu_spi_miso <= mcu_flash_miso;
	else if (mcu_spi_fpga == 0)
		mcu_spi_miso <= mcu_com_miso;
	else
		mcu_spi_miso <= fpga_dmx_send;
		
//************************************************************/
//		SD卡控制
//************************************************************/
wire		sd_mcu_clk, sd_mcu_cmd_oe, sd_mcu_cmd_out;
reg		sd_clk_out, sd_cmd_oe, sd_cmd_out;
wire	[3:0]	sd_dat_in;

//SD卡插入检测
sd_cd_dect sd_cd_dect(
		.resetb(resetb),
		.sclk(sclk),
		
		.t_ms_sync(sync_us[10]),
               
		.sd_cd(sd_cd),
		
		.sd_valid(sd_valid),
		
		.tout()
		);

//mcu通过FPGA直接控制SD卡
mcu_sd_cnt mcu_sd_cnt(
		.resetb(resetb),
		.sclk(sclk),
                
		.mcu_sd_en(mcu_sd_en),
		.mcu_fpga_ctrl(mcu_fpga_ctrl),
		
		.mcu_spi_clk(mcu_spi_clk),
		.mcu_spi_mosi(mcu_spi_mosi),
		.mcu_spi_miso(mcu_sd_miso),
                
		.sd_clk(sd_mcu_clk),
		.sd_cmd_oe(sd_mcu_cmd_oe),
		.sd_cmd_out(sd_mcu_cmd_out),
		.sd_cmd_in(sd_cmd_in),
		.sd_dat_oe(),
		.sd_dat_out(),
		.sd_dat_in(sd_dat_in),
		
		.tout()
		);
		
always	@( * )
	if (mcu_sd_en == 0) begin
		sd_clk_out <= sd_play_clk;
		sd_cmd_oe <= sd_play_cmd_oe;
		sd_cmd_out <= sd_play_cmd_out;
		end
	else begin
		sd_clk_out <= sd_mcu_clk;
		sd_cmd_oe <= sd_mcu_cmd_oe;
		sd_cmd_out <= sd_mcu_cmd_out;
		end

always	@( * )
	sd_play_data <= sd_dat_in;

//SD卡输出控制
assign	sd_clk = sd_clk_out;
assign	sd_cmd_sdi = (sd_cmd_oe == 1)?sd_cmd_out:1'bz;

//SD卡输入控制
assign	sd_cmd_in = sd_cmd_sdi;
assign	sd_dat_in = {sd_dat3_cs, sd_dat2, sd_dat1, sd_dat0_sdo};

//************************************************************/
//		DMX发送信号
//************************************************************/
always @( * )
	if (mcu_sd_en == 1)
		mcu_dmx_ten <= 1;
	else
		mcu_dmx_ten <= mcu_fpga_ctrl;

//************************************************************/
//		调试接口
//************************************************************/
//assign	tout = {pre_flag, send_flag, spi2_mosi, spi2_clk, spi2_cs, rec_flag_a, sd_cmd_oe, sd_cmd_out, 1'b0, mcu_flash_en, mcu_sd_en, sd_cmd_oe, sd_cmd_out, boot_tout[0], comm_tout[4], rec_flag, comm_tout[1:0], send_flag_com};//, input_active};
assign	tout = d_tout;

endmodule


